package com.qilin.hscs.service.impl;


import com.qilin.hscs.dto.*;
import com.qilin.hscs.enums.ResultEnum;
import com.qilin.hscs.enums.UserHostUsingStatus;
import com.qilin.hscs.enums.UserRoleEnum;
import com.qilin.hscs.exception.SMException;
import com.qilin.hscs.pojo.*;

import com.qilin.hscs.repository.HostRepository;
import com.qilin.hscs.repository.MqttUserRepository;
import com.qilin.hscs.repository.UserHostRepository;
import com.qilin.hscs.service.HostService;
import com.qilin.hscs.service.UserHostService;
import com.qilin.hscs.service.UserService;
import com.qilin.hscs.util.ResultVOUntil;
import com.qilin.hscs.vo.ResultVO;

import com.qilin.hscs.vo.UserHostVO;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author 胡晓军
 * @date 2018-5-9
 */
@Service
@Transactional
public class UserHostServiceImpl implements UserHostService{

    @Autowired
    private UserHostRepository userHostRepository;
    @Autowired
    private UserService userService;
    @Autowired
    private HostService hostService;
    @Autowired
    private MqttUserRepository mqttUserRepository;

    @Autowired
    private HostRepository hostRepository;
    @Autowired
    private JPAQueryFactory  query;

    private static final String defaultHostName = "主机";

    /**
     * 用户绑定主机，所有用户都可以操作
     * @param dto
     * @return
     */
    @Override
    public ResultVO bindHost(UserHostBindDto dto) {
        //用户不存在就抛出异常，而主机数据库中可以不存在，不存在就创建这个主机
        User user = userService.findOneByPhone(dto.getPhone());

        Host host = hostRepository.findByMac(dto.getMac());

        //如果数据库中已经有这个主机了，那就直接绑定，如果没有，就先把主机信息存入库，再绑定
        if (host == null) {
            Host newHost = new Host();
            newHost.setMac(dto.getMac());
            newHost.setName(defaultHostName);
            host=hostRepository.save(newHost);
        }

        //如果这个用户已经绑定过了这台主机就抛出异常
        UserHost isBinded = userHostRepository.findByPhoneAndMac(dto.getPhone(), dto.getMac());
        if (isBinded != null) {
            throw new SMException(ResultEnum.USER_HOST_IS_BIND);
        }

        List<UserHost> userHosts = userHostRepository.findUserHostByUserId(user.getId());
        //当用户绑定一个主机时，首先先把他所有已绑定的主机状态改成下线，刚绑定的那个主机状态为上线状态
        userHosts.forEach(e->e.setIsUse(UserHostUsingStatus.UNDERLINE.getCode()));

        UserHost userHost = new UserHost();

        //如果当前主机下还没有用户，那么绑定的用户角色就为管理员，否则默认为无权限用户,同时要把mqtt表中用户的权限修改掉
        List<UserHostVO> users = userHostRepository.findUserByHostId(host.getId());
        if (users == null || users.size() == 0) {
            userHost.setRole(UserRoleEnum.ADMIN.getRole());
        }

        //用户绑定主机
        userHost.setHostId(host.getId());
        userHost.setUserId(user.getId());
        UserHost re = userHostRepository.save(userHost);
        //把角色同步到mqtt角色表中
        modifyMqttUserRole(dto.getPhone(),re.getRole());
        if (re != null) {
            UserHostVO vo = new UserHostVO();
            vo.setIsUse(re.getIsUse());
            vo.setRole(re.getRole());
            vo.setHostMac(host.getMac());
            vo.setHostName(host.getName());
            return ResultVOUntil.success(vo);
        }
        return null;
    }

    @Override
    public ResultVO findHostsByUserPhone(String phone) {
        User user = userService.findOneByPhone(phone);
        List<UserHostVO> hosts = userHostRepository.findHostByUserId(user.getId());
        return ResultVOUntil.success(hosts);
    }

    @Override
    public ResultVO findUsersInHost(String mac) {
        Host host = hostService.findOneByMac(mac);
        List<UserHostVO> users = userHostRepository.findUserByHostId(host.getId());
        Map<String, Object> data = new HashMap<>(2);
        data.put("hostMac", mac);
        data.put("userList", users);
        return ResultVOUntil.success(data);
    }

    /**
     * 管理员分配权限，可以给用户分配为一般用户或者是无权用户
     * @param dto
     * @return
     */
    @Override
    public ResultVO allotRoles(AllotRolesDto dto) {
        UserHost userHost = userHostRepository.findByPhoneAndMac(dto.getPhone(), dto.getMac());
        //将用户主机对应表中的权限修改，同时将用户在mqtt中的权限也修改
        userHost.setRole(dto.getRole());
        userHostRepository.save(userHost);
        modifyMqttUserRole(dto.getPhone(),dto.getRole());
        return ResultVOUntil.success();
    }

    /**
     * 转让管理员权限，管理员降级为普通用户
     * @param dto
     * @return
     */
    @Override
    public ResultVO transferAdmin(TransferAdminDto dto) {
        UserHost giver = findByPhoneAndMac(dto.getGive(), dto.getMac());
        UserHost acceptor = findByPhoneAndMac(dto.getAccept(), dto.getMac());
        giver.setRole(UserRoleEnum.USER.getRole());
        acceptor.setRole(UserRoleEnum.ADMIN.getRole());
        //将管理员的身份降级为普通用户
        userHostRepository.save(giver);
        //升级为管理员
        userHostRepository.save(acceptor);
        //同时修改mqtt中的权限
        modifyMqttUserRole(dto.getGive(),UserRoleEnum.USER.getRole());
        modifyMqttUserRole(dto.getAccept(),UserRoleEnum.ADMIN.getRole());
        return ResultVOUntil.success();
    }

    @Override
    public ResultVO switchHost(SwitchHostDto dto) {
        if (!StringUtils.isEmpty(dto.getCurrentMac())) {
            UserHost current = findByPhoneAndMac(dto.getPhone(), dto.getCurrentMac());
            current.setIsUse(UserHostUsingStatus.UNDERLINE.getCode());
            userHostRepository.save(current);
        }

        UserHost target = findByPhoneAndMac(dto.getPhone(), dto.getTargetMac());
        // 切换主机后，当前主机状态为下线，目标主机上线

        target.setIsUse(UserHostUsingStatus.ONLINE.getCode());

        userHostRepository.save(target);
        //同时将mqtt中的权限修改为目标主机的权限
        modifyMqttUserRole(dto.getPhone(), target.getRole());
        return ResultVOUntil.success();
    }

    @Override
    public ResultVO releaseHost(ReleaseHostDto dto) {
        UserHost userHost=findByPhoneAndMac(dto.getPhone(), dto.getMac());
        userHostRepository.delete(userHost);
        return ResultVOUntil.success();
    }

    private void modifyMqttUserRole(String phone,Integer role) {
        MqttUser mqttUser = mqttUserRepository.findByUsername(phone);
        if (mqttUser == null) {
            throw new SMException(ResultEnum.USER_NOT_FOUND);
        }
        mqttUser.setRole(role);
        mqttUserRepository.save(mqttUser);
    }


    private UserHost findByPhoneAndMac(String phone, String mac) {
        UserHost userHost = userHostRepository.findByPhoneAndMac(phone,mac);
        if (userHost == null) {
            throw new SMException(ResultEnum.USER_HOST_NOT_FOUND);
        }
        return userHost;
    }
}
